package states.loading;

import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.loading.DeferredResource;
import org.newdawn.slick.loading.LoadingList;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

import resources.ResourceException;
import resources.ResourceManager;

public abstract class BaseLoadingGameState extends BasicGameState {
	protected static final Logger _tracer = Logger.getLogger(BaseLoadingGameState.class.getName()); 
	
	private static int LOADING_SCREEN_ID 		= 0;
	private static int LOADING_BAR_ID 			= 1;
	private static int LOADING_BAR_TICK_ID 		= 2;

	protected Vector2f backgroundPosition;
	protected Vector2f barPosition;
	protected Vector2f barSize;
	protected Vector2f tickDisplacement;
	protected Vector2f tickInnerDisplacement;
	
	private Image loadingBackground;
	private Image loadingBarTick;
	private Image loadingBar;
	
	private ResourceManager _resourceManager;
	
	/**
	 * The background Image path, it will be used to locate the file before the 
	 * resource manager is loaded.
	 */
	protected String backgroundScreenImagePath;
	/**
	 * The the loading bar Image path, it will be used to locate the file before the 
	 * resource manager is loaded.
	 */
	protected String loadingBarImagePath;
	/**
	 * The tick for the loading bar Image path, it will be used to locate the file before the 
	 * resource manager is loaded.
	 */
	protected String barTickImagePath;
	
	private IAfterLoading _afterLoadingSnippet;
	
	private int maxNumberOfTicks;
	
	public BaseLoadingGameState(){
		
		barPosition = new Vector2f(300,400);
		
		tickDisplacement = new Vector2f(0,0);
		
		tickInnerDisplacement = new Vector2f(0,0);
		
		barSize = new Vector2f(0,0);
	}
	
	public void setResourceManager(ResourceManager resourceManager){
		_resourceManager = resourceManager;
	}
	
	public void setAfterLoading(IAfterLoading afterLoadingSnippet){
		_afterLoadingSnippet = afterLoadingSnippet;
	}
	
	@Override
	public void enter(GameContainer gc, StateBasedGame sbg) throws SlickException {
		// erase mouse
		//gc.setMouseGrabbed(true);
	}
	
	@Override
	public void leave(GameContainer gc, StateBasedGame sbg) throws SlickException {
	}
	
	@Override
	public void init(GameContainer gc, StateBasedGame sbg) throws SlickException {
		
//		gc.setMinimumLogicUpdateInterval(0);
//		gc.setMaximumLogicUpdateInterval(0);
		
		_tracer.finest("Entered Resource Loader State");
		
		// Load needed resources before Resource Manager is available
		try {
			
			if(backgroundScreenImagePath != null){
				loadingBackground = _resourceManager.loadImage(LOADING_SCREEN_ID, backgroundScreenImagePath, "loading background screen");
			}
			
			if(loadingBarImagePath != null){
				loadingBar = _resourceManager.loadImage(LOADING_BAR_ID, loadingBarImagePath, "loading Bar");
			}
			
			if(barTickImagePath != null){
				loadingBarTick = _resourceManager.loadImage(LOADING_BAR_TICK_ID, barTickImagePath, "loading bar tick");
			}
		
		} catch (ResourceException e) {
			throw new SlickException("Could not obtain resources for loading screen", e);
		}
		
		maxNumberOfTicks = (int) ( (barSize.x-tickDisplacement.x) / (loadingBarTick.getWidth()+tickInnerDisplacement.x));
	}

	@Override
	public void render(GameContainer arg0, StateBasedGame arg1, Graphics arg2)
			throws SlickException {

		// background
		loadingBackground.draw();
		// loading bar 
		loadingBar.draw(barPosition.x, barPosition.y);
		// criar loading bar background
		float displacementX = (tickDisplacement != null) ? tickDisplacement.x : 0;
		float displacementY = (tickDisplacement != null) ? tickDisplacement.y : 0;
		int ticks = (int)(percentage * maxNumberOfTicks / 100.0f);
		
		for(int i = 0; i < ticks; i++){
			loadingBarTick.draw(barPosition.x + displacementX+ (i*(loadingBarTick.getWidth() + tickInnerDisplacement.x)) , barPosition.y + displacementY + tickInnerDisplacement.y);
		}
	}

	int percentage = 0;
	
	@Override
	public void update(GameContainer gc, StateBasedGame sbg, int delta)
			throws SlickException {
		// load the resources
		if (LoadingList.get().getRemainingResources() > 0) { 
	        DeferredResource nextResource = LoadingList.get().getNext(); 
	        try {
	        	nextResource.load();
				
				// update percentages
				percentage = 100 * (LoadingList.get().getTotalResources() - LoadingList.get().getRemainingResources()) / LoadingList.get().getTotalResources();
			} catch (IOException ioEx) {
				_tracer.throwing(getClass().getCanonicalName(),"update(GameContainer gc, StateBasedGame sbg, int delta)", ioEx);
			}
		}else{
			percentage = 100;
			if(_afterLoadingSnippet != null){
				_afterLoadingSnippet.execute(gc, sbg);
			}
			//
		}
	}

	

	public void setLoadData(InputStream is) throws Exception {
		_resourceManager.loadResources(is, true);
	}
}
